<template>
  <div class="message">
    <!-- 最近聊天 -->
    <div class="message-sidebar">
      <!-- 通过用户昵称查询消息 -->
      <div class="search-box">
        <a-input
          v-model:value="searchKeyword"
          placeholder="搜索用户昵称"
          size="large"
          allow-clear
        >
          <template #prefix>
            <search-outlined />
          </template>
        </a-input>
      </div>

      <!-- 最近聊天列表 -->
      <div class="recent-chats">
        <div
          v-for="chat in filteredChats"
          :key="chat.id"
          class="chat-item"
          :class="{ active: activeChatId === chat.userId }"
          @click="selectChat(chat)"
          @contextmenu.prevent="showContextMenu($event, chat)"
        >
          <a-avatar
            :src="chat.avatarUrl"
            size="large"
          />

          <div class="chat-info">
            <div class="username">{{ chat.nickname }}</div>
            <div class="last-message">{{ chat.content }}</div>
          </div>

          <div
            class="unread-count"
            v-if="chat.unreadCount > 0"
          >
            {{ chat.unreadCount }}
          </div>
        </div>
      </div>

      <!-- 右键菜单选项 -->
      <a-menu
        v-model:openKeys="contextMenuOpen"
        v-model:selectedKeys="contextMenuSelected"
        :style="contextMenuStyle"
        v-if="showContextMenuFlag"
        class="context-menu"
        @click="handleContextMenuClick"
      >
        <a-menu-item
          key="markRead"
          @click="markChatAsRead"
        >
          标记为已读
        </a-menu-item>
        <a-menu-item
          key="delete"
          danger
        >
          删除聊天
        </a-menu-item>
      </a-menu>
    </div>

    <!-- 聊天详情 -->
    <div class="message-content">
      <!-- 如果未点击最近的消息，则显示 LOGO -->
      <div
        v-if="!activeChat"
        class="empty-state"
      >
        <img
          src="@/assets/logo.jpg"
          alt="Logo"
          class="logo"
        />
      </div>

      <div v-else>
        <!-- 目标用户信息 -->
        <div class="chat-header">
          <div class="header-info">
            <div class="username">{{ activeChat.nickname }}</div>
          </div>
        </div>

        <!-- 聊天内容 -->
        <div
          class="chat-history"
          ref="chatHistory"
        >
          <div
            v-for="message in currentMessageList"
            class="message-item"
            :class="{ 'is-me': message.senderId == userState.getUserId }"
          >
            <template v-if="message.senderId != userState.getUserId">
              <a-avatar
                :src="activeChat?.avatarUrl"
                size="default"
                class="message-avatar"
              />
              <div class="message-content-detail">
                <div class="message-time">{{ timeFormat(message.sendTime) }}</div>
                <div
                  class="message-text"
                  v-html="message.content"
                ></div>
              </div>
            </template>

            <template v-else>
              <div class="message-content-detail">
                <div class="message-time">{{ timeFormat(message.sendTime) }}</div>
                <div
                  class="message-text"
                  v-html="message.content"
                ></div>
                <div class="read-status">
                  {{ message.isRead ? '已读' : '未读' }}
                </div>
              </div>
              <a-avatar
                :src="userState.getUserAvatar"
                size="default"
                class="message-avatar"
              />
            </template>
          </div>
        </div>

        <!-- 表情、输入框和发送按钮 -->
        <div
          class="emoji-picker"
          v-if="showEmojiPicker"
        >
          <div
            v-for="emoji in emojis"
            :key="emoji"
            class="emoji-item"
            @click="selectEmoji(emoji)"
          >
            {{ emoji }}
          </div>
        </div>

        <div class="chat-input">
          <div class="input-tools">
            <span
              class="emoji-btn"
              @click="toggleEmojiPicker"
            >
              😊
            </span>
          </div>
          <a-textarea
            v-model:value="inputMessage"
            placeholder="输入消息..."
            :rows="2"
            :disabled="!activeChat"
            @keydown.enter="handleEnterKey"
          />
          <a-button
            type="primary"
            class="send-button"
            :disabled="!activeChat"
            @click="sendMessage"
          >
            发送
          </a-button>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { SearchOutlined } from '@ant-design/icons-vue'
import { getAccessToken } from '@/utils/auth'
import { useWebSocket } from '@vueuse/core'
import { useUserStore } from '@/store/modules/user'
import {
  clearUnreadCount,
  createConversation,
  getConversationId,
  getConversationIsVisible,
  getMessageList,
  getRecentMessageList,
  setConversationVisible
} from '@/api/message'
import { getUserProfile } from '@/api/user'
import type { CvMessageRecentRespVO, CvMessageRespVO } from '@/types/message'
import dayjs from 'dayjs'
import { message } from 'ant-design-vue'

const userState = useUserStore()
const router = useRouter()
const route = useRoute()

const recentMessageList = ref<CvMessageRecentRespVO[]>([])
const currentMessageList = ref<CvMessageRespVO[]>([])
onMounted(async () => {
  document.addEventListener('click', handleClickOutside)

  recentMessageList.value = await getRecentMessageList()

  const userId = route.query.userId as number

  await router.replace({
    query: {
      ...route.query,
      userId: undefined
    }
  })

  if (userId && userId !== userState.getUserId) {
    const conversationId = await getConversationId(userState.getUserId, userId)
    if (conversationId) {
      const isVisible = await getConversationIsVisible(conversationId)
      if (!isVisible) {
        await setConversationVisible(conversationId, true)
      }
      recentMessageList.value = await getRecentMessageList()
    } else {
      const reqVO = {
        targetUserId: userId
      }
      const sessionId = await createConversation(reqVO)

      const res = await getUserProfile(userId)
      recentMessageList.value.unshift({
        conversationId: sessionId,
        userId: userId,
        nickname: res.nickname,
        avatar: 0,
        avatarUrl: res.avatar,
        content: '',
        sendTime: '',
        unreadCount: 0
      })
    }

    for (const item of recentMessageList.value) {
      if (userId === item.userId) {
        recentMessageList.value = recentMessageList.value.filter(item => item.userId !== userId)
        recentMessageList.value.unshift(item)
        await selectChat(item)
      }
    }
  }
})

onUnmounted(() => {
  document.removeEventListener('click', handleClickOutside)
})

const socketServer = ref(
  'http://127.0.0.1:9001/infra/ws'.replace('http', 'ws') + '?token=' + getAccessToken()
)
const getIsOpen = computed(() => status.value === 'OPEN')
const { status, data, send, close, open } = useWebSocket(socketServer.value, {
  autoReconnect: true,
  heartbeat: true,
  onConnected(ws) {
    console.log('WebSocket 连接成功')
  },
  onDisconnected(ws, event) {
    console.log('连接断开', event)
  }
})

/**
 * websocket 消息接收
 */
watchEffect(async () => {
  if (!data.value) {
    return
  }

  try {
    if (data.value === 'pong') {
      return
    }

    // 解析 type 消息类型
    const jsonMessage = JSON.parse(data.value)
    const type = jsonMessage.type
    const content = JSON.parse(jsonMessage.content)
    if (!type) {
      message.error('未知的消息类型：' + data.value)
      return
    }

    if (type === 'infra-message-receive') {
      const single = content.single
      if (single) {
        const sendTime = Date.now()
        if (!recentMessageList.value.find(item => item.conversationId === content.conversationId)) {
          recentMessageList.value = await getRecentMessageList()
        } else {
          for (const item of recentMessageList.value) {
            if (item.conversationId === content.conversationId) {
              item.content = content.content
              item.sendTime = sendTime
              item.unreadCount = item.unreadCount + 1
              break
            }
          }
        }

        // 置顶
        for (const item of recentMessageList.value) {
          if (item.conversationId === content.conversationId) {
            recentMessageList.value = recentMessageList.value.filter(
              item => item.conversationId !== content.conversationId
            )
            recentMessageList.value.unshift(item)
            break
          }
        }

        // 如果是当前会话，则添加到消息列表中并通知对方已读
        if (activeChat.value?.conversationId === content.conversationId) {
          currentMessageList.value.push({
            id: content.id,
            senderId: content.senderId,
            receiverId: content.receiverId,
            content: content.content,
            isRead: content.isRead,
            sendTime: sendTime
          })

          nextTick(() => {
            scrollToBottom()
          })

          clearUnreadCount(content.conversationId)
          // 清除未读消息
          for (const item of recentMessageList.value) {
            if (item.conversationId === content.conversationId) {
              item.unreadCount = 0
            }
          }

          // 通知对方已读
          const messageSend = JSON.stringify({
            type: 'read',
            conversationId: activeChat.value.conversationId,
            targetUserId: activeChat.value.userId
          })

          const jsonMessage = JSON.stringify({
            type: 'infra-message-send',
            content: messageSend
          })
          send(jsonMessage)
        }
      }
      return
    }

    if (type === 'infra-message-read') {
      // 让 conversationId 下的所有已读
      if (activeChat.value.conversationId == content.conversationId) {
        for (const item of currentMessageList.value) {
          if (item.id === content.messageId) {
            item.isRead = true
          }
        }
      }
      return
    }
  } catch (error) {
    console.error('处理消息发生异常：' + data.value)
    // message.error('处理消息发生异常：' + data.value)
  } finally {
    data.value = null
  }
})

const activeChatId = ref(null)
const searchKeyword = ref('')
const inputMessage = ref('')
const showEmojiPicker = ref(false)
const chatHistory = ref(null)
const emojis = ['😀', '😃', '😄', '😁', '😆', '😅', '😂', '🤣', '😊', '😇']

// 右键菜单相关
const contextMenuOpen = ref([])
const contextMenuSelected = ref([])
const showContextMenuFlag = ref(false)
const contextMenuStyle = ref({})
const selectedChat = ref(null)

const activeChat = computed(() => {
  return recentMessageList.value.find(chat => chat.userId === activeChatId.value)
})

/**
 * 过滤最近聊天列表
 */
const filteredChats = computed(() => {
  return recentMessageList.value.filter(item =>
    item.nickname.toLowerCase().includes(searchKeyword.value.toLowerCase())
  )
})

/**
 * 选择聊天
 */
const selectChat = async (item: any) => {
  activeChatId.value = item.userId
  currentMessageList.value = await getMessageList(item.conversationId)
  // 标记为已读
  const chat = recentMessageList.value.find(c => c.conversationId === item.conversationId)
  if (chat) {
    chat.unreadCount = 0
    clearUnreadCount(chat.conversationId)
  }
  await nextTick(() => {
    scrollToBottom()
  })

  // 通知对方已读
  const messageSend = JSON.stringify({
    type: 'read',
    conversationId: item.conversationId,
    targetUserId: item.userId
  })

  const jsonMessage = JSON.stringify({
    type: 'infra-message-send',
    content: messageSend
  })
  send(jsonMessage)
}

/**
 * 发送消息
 */
const sendMessage = () => {
  if (!inputMessage.value.trim() || !activeChat.value) return

  const content = inputMessage.value.replace(/\n/g, '<br>')

  currentMessageList.value.push(<any>{
    conversationId: activeChat.value.conversationId,
    senderId: userState.getUserId,
    receiverId: activeChat.value.userId,
    content: content,
    sendTime: Date.now()
  })

  const messageSend = JSON.stringify({
    type: 'message',
    conversationId: activeChat.value.conversationId,
    targetUserId: activeChat.value.userId,
    content: content
  })

  const jsonMessage = JSON.stringify({
    type: 'infra-message-send',
    content: messageSend
  })
  send(jsonMessage)

  // 更新最近聊天列表，将当前聊天移到最前面
  const chat = recentMessageList.value.find(c => c.userId === activeChatId.value)
  if (chat) {
    // 更新最后一条消息
    chat.content = content
    // 将当前聊天移到最前面
    recentMessageList.value = [
      chat,
      ...recentMessageList.value.filter(c => c.conversationId !== chat.conversationId)
    ]
  }

  inputMessage.value = ''
  scrollToBottom()
}

/**
 * 自动滚到底部
 */
const scrollToBottom = () => {
  nextTick(() => {
    if (chatHistory.value) {
      chatHistory.value.scrollTop = chatHistory.value.scrollHeight
    }
  })
}

/**
 * 表情
 */
const toggleEmojiPicker = () => {
  showEmojiPicker.value = !showEmojiPicker.value
}

const selectEmoji = emoji => {
  inputMessage.value += emoji
  showEmojiPicker.value = false
}

/**
 * 右键菜单功能
 */
const showContextMenu = (event, chat) => {
  event.preventDefault()
  selectedChat.value = chat
  showContextMenuFlag.value = true
  contextMenuStyle.value = {
    left: `${event.pageX}px`,
    top: `${event.pageY}px`,
    position: 'absolute'
  }
}

/**
 * 标记会话为已读
 */
const markChatAsRead = async () => {
  if (selectedChat.value) {
    selectedChat.value.unreadCount = 0
    showContextMenuFlag.value = false
    await clearUnreadCount(selectedChat.value.conversationId)

    // 通知对方已读
    const messageSend = JSON.stringify({
      type: 'read',
      conversationId: selectedChat.value.conversationId,
      targetUserId: selectedChat.value.userId
    })

    const jsonMessage = JSON.stringify({
      type: 'infra-message-send',
      content: messageSend
    })
    send(jsonMessage)
  }
}

/**
 * 右键菜单点击事件
 */
const handleContextMenuClick = ({ key }) => {
  switch (key) {
    case 'markRead':
      markChatAsRead()
      break
    case 'delete':
      deleteChat()
      break
  }
}

/**
 * 移除最近消息【隐藏会话】
 */
const deleteChat = async () => {
  if (selectedChat.value) {
    recentMessageList.value = recentMessageList.value.filter(
      chat => chat.conversationId !== selectedChat.value.conversationId
    )
    if (activeChatId.value === selectedChat.value.userId) {
      activeChatId.value = null
      currentMessageList.value = []
    }
    showContextMenuFlag.value = false
    await setConversationVisible(selectedChat.value.conversationId, false)
  }
}

/**
 * 点击外部关闭右键菜单
 */
const handleClickOutside = event => {
  if (!event.target.closest('.context-menu')) {
    showContextMenuFlag.value = false
  }
}

const handleEnterKey = event => {
  if (event.shiftKey) {
    return
  }

  event.preventDefault()
  sendMessage()
  inputMessage.value = ''
}

/**
 * 时间格式化
 */
const timeFormat = (time: string) => {
  if (!time) {
    return ''
  }
  return dayjs(time).format('YYYY-MM-DD HH:mm:ss')
}
</script>

<style scoped>
.message {
  display: flex;
  height: 650px;
  justify-content: center;
}

.message-sidebar {
  width: 300px;
  height: 650px;
  display: flex;
  flex-direction: column;
  border: 1px solid #e5e5e5;
}

.search-box {
  height: 75px;
  padding: 16px;
  border-bottom: 1px solid #e5e5e5;
}

.recent-chats {
  flex: 1;
  overflow-y: auto;
}

.chat-item {
  display: flex;
  align-items: center;
  padding: 12px 16px;
  cursor: pointer;
  transition: background-color 0.3s;
  border-bottom: 1px solid #e6f7ff;
}

.chat-item:hover {
  background-color: #f5f5f5;
}

.chat-item.active {
  background-color: #e6f7ff;
}

.chat-info {
  flex: 1;
  margin-left: 12px;
}

.username {
  font-weight: 500;
}

.last-message {
  color: #666;
  font-size: 12px;
  margin-top: 4px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  width: 200px;
}

.unread-count {
  background-color: #ff4d4f;
  color: white;
  font-size: 12px;
  padding: 0 7px;
  border-radius: 100%;
}

.message-content {
  flex: 1;
  height: 650px;
  border: 1px solid #e5e5e5;
}

.empty-state {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  flex-direction: column;
}

.logo {
  width: 120px;
  margin-bottom: 16px;
}

.chat-header {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 75px;
  border-bottom: 1px solid #e5e5e5;
  font-size: 17px;
  font-weight: bolder;
}

.chat-history {
  flex: 1;
  height: 480px;
  padding: 16px;
  overflow-y: auto;
  background-color: #f5f5f5;
}

.message-item {
  margin-bottom: 16px;
  display: flex;
  align-items: flex-start;
}

.message-item.is-me {
  justify-content: flex-end;
}

.message-avatar {
  margin: 0 8px;
}

.message-content-detail {
  max-width: 60%;
  padding: 8px 12px;
  border-radius: 4px;
  background-color: #fff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.message-item.is-me .message-content-detail {
  background-color: #e6f7ff;
}

.message-time {
  font-size: 12px;
  color: #999;
  margin-bottom: 4px;
}

.message-text {
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 14px;
  color: #333;
}

.read-status {
  font-size: 12px;
  color: #999;
  text-align: right;
  margin-top: 4px;
}

.chat-input {
  padding: 16px;
  border-top: 1px solid #e5e5e5;
  background-color: #fff;
  display: flex;
  align-items: center;
}

.input-tools {
  margin-right: 12px;
}

.chat-input textarea {
  flex: 1;
  resize: none;
}

.send-button {
  margin-left: 12px;
}

.emoji-picker {
  position: absolute;
  z-index: 1000;
  display: grid;
  grid-template-columns: repeat(10, 1fr);
  gap: 8px;
  padding: 12px;
  background: #fff;
  border: 1px solid #e5e5e5;
  border-radius: 4px;
  margin-bottom: 8px;
  max-height: 200px;
  overflow-y: auto;
  bottom: 110px;
}

.emoji-item {
  cursor: pointer;
  font-size: 20px;
  text-align: center;
  padding: 4px;
  border-radius: 4px;
}

.emoji-item:hover {
  background: #f0f0f0;
}

.emoji-btn {
  cursor: pointer;
  font-size: 20px;
  padding: 4px;
  border-radius: 4px;
}

.emoji-btn:hover {
  background: #f0f0f0;
}

.context-menu {
  position: fixed;
  z-index: 1000;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  border-radius: 4px;
}
</style>
